/**
 * 
 */
package com.fox.webapp.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import jxl.NumberCell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.fox.webapp.domain.Account;
import com.fox.webapp.domain.Broker;
import com.fox.webapp.domain.CommissionRecord;
import com.fox.webapp.domain.Person;
import com.fox.webapp.persistent.AccountRepository;
import com.fox.webapp.persistent.BrokerRepository;
import com.fox.webapp.persistent.CommissionRecordRepository;
import com.fox.webapp.persistent.PersonRepository;
import com.fox.webapp.service.IAccountService;

/**
 * @author yockii
 *
 */
@Service
public class AccountService implements IAccountService {
	private static final Logger logger = LoggerFactory.getLogger(AccountService.class);
	
	@Autowired
	private AccountRepository accountRepository;
	@Autowired
	private CommissionRecordRepository commissionRecordRepository;
	@Autowired
	private PersonRepository personRepository;
	@Autowired
	private BrokerRepository brokerRepository;
	
	@Override
	public Account addNewAccount(Account account, String brokerId,
			Person person) {
		Broker b = brokerRepository.findOne(new ObjectId(brokerId));

		Account a = accountRepository.findByBrokerNameAndAccountNo(b.getName(), account.getAccountNo());
		if(a != null){
			return null;
		}
		
		account.setBroker(b);
		account.setLastPay(0.0);
		account.setTotalCommission(0.0);
		account.setTotalPayed(0.0);
		if(account.getMinToPay() == null || account.getMinToPay() < 1){
			account.setMinToPay(1.0);
		}
		account.setPerson(person);
		account = accountRepository.save(account);

		// Person p = getPersonById(person.getId());
		// List<Account> accountList = p.getAccounts();
		// if (accountList == null) {
		// accountList = new ArrayList<Account>();
		// }
		// accountList.add(account);
		// p.setAccounts(accountList);
		// personRepository.updatePersonAccount(p);
		return account;
	}
	
	@Override
	public boolean removeMyAccount(Person person, String id) {
		if (id != null && person != null) {
			String accountId = id.trim();
			Account account = accountRepository.findByIdAndPerson(
					new ObjectId(accountId), person);
			if (account != null) {
				accountRepository.delete(account);
			}
			return true;
		}
		return false;
	}
	
	@Override
	public List<Account> getMyAccounts(Person p) {
		if (p != null) {
			return accountRepository.findByPerson(p);
		}
		return new ArrayList<Account>();
	}

	@Override
	public boolean updateAccountName(Person person, Account account) {
		if (person != null && account.getId() != null) {
			Account a = accountRepository.findByIdAndPerson(account.getId(),
					person);
			if (a != null) {
				a = accountRepository.updateAccountOnlySelfDesc(account);
				return (account.getSelfDesc() == null && a.getSelfDesc() == null)
						|| (account.getSelfDesc().equals(a.getSelfDesc()));
			}
		}
		return false;
	}

	@Override
	public int addCommission(String brokerName, String accountNo,
			Double commission, Date time) {
		List<CommissionRecord> crList = commissionRecordRepository.findByBrokerNameAndAccountNoAndTime(brokerName, accountNo, time);
		if(crList.isEmpty()){
			CommissionRecord commissionRecord = new CommissionRecord();
			commissionRecord.setAccountNo(accountNo);
			commissionRecord.setBrokerName(brokerName.toLowerCase());
			commissionRecord.setCommission(commission);
			commissionRecord.setTime(time);
			commissionRecordRepository.save(commissionRecord);
			
			List<Account> al = accountRepository.findByAccountNo(accountNo);
			Account account = null;
			for (Account a : al) {
				if(a.getBroker().getName().equalsIgnoreCase(brokerName)){
					account = a;
					break;
				}
			}
			if(account != null){
				accountRepository.addCommission(account, commission);
				personRepository.addCredit(account.getPerson(), commission);
				String oid = account.getPerson().getReferenceId();
				if(StringUtils.hasText(oid)){
					Person p = personRepository.findOne(new ObjectId(oid));
					Integer refLevel = p.getRefLevel();

					personRepository.addReferCommission(p, commission * 0.01 * (refLevel == null?1:refLevel));
				}
				
				return CommissionRecord.SAVE_SUCCESS;
			}
			return CommissionRecord.NO_SUCH_ACCOUNT;
		}
		return CommissionRecord.ALREADY_SAVED;
	}

	@Override
	public Page<CommissionRecord> getMyCommission(Account account, int page,
			int size) {
		Page<CommissionRecord> crPage = commissionRecordRepository.findAllMyAccountsCommissionRecord(Arrays.asList(account), new PageRequest(page, size, Direction.DESC, "time"));
		return crPage;
	}

	@Override
	public Account getAccount(ObjectId id) {
		return accountRepository.findOne(id);
	}

	@Override
	public long getMyAccountCount(Person p) {
		return accountRepository.countMine(p);
	}

	@Override
	public Page<Account> getAccountWithCondition(Account account, int page,
			int length) {
		if(account.getPerson() != null && StringUtils.hasText(account.getPerson().getUsername())){
			account.setPerson(personRepository.findByUsername(account.getPerson().getUsername()));
		}
		return accountRepository.findAccountByCondition(account, new PageRequest(page, length));
	}

	@Override
	public String recordCommissionWithExcel(InputStream inputStream) throws BiffException, IOException {
		Workbook wb = Workbook.getWorkbook(inputStream);
		Sheet sheet = wb.getSheet(0);
		int rowNum = sheet.getRows();
		String errMsg="";
		String accountNo, brokerName;
		double commission;
		for (int i = 0; i < rowNum; i++) {
			try{
				accountNo = sheet.getCell(0, i).getContents();
				brokerName = sheet.getCell(1, i).getContents();
				commission = ((NumberCell)sheet.getCell(2, i)).getValue();
				Account account = accountRepository.recordAccountCommission(accountNo, brokerName, commission);
				if(account == null){
					errMsg += "循环行" + i + "失败, 未找到账号"+accountNo;
				} else {
					commissionRecordRepository.updateAllAccountCommission2Backed(accountNo, brokerName);
				}
			} catch (Exception e) {
				errMsg += "循环行" + i + "失败，原因：" + e.getLocalizedMessage();
			}
		}
		return StringUtils.hasText(errMsg)?errMsg:"ok";
	}

	@Override
	public int commissionRefundDone(Account account, Double commissionRefund) {
		Account a = accountRepository.recordAccountCommission(account.getAccountNo(), account.getBrokerName(), commissionRefund);
		if(a != null){
			commissionRecordRepository.updateAllAccountCommission2Backed(account.getAccountNo(), account.getBrokerName());
		}
		return 0;
	}

}
